#![windows_subsystem = "windows"]
use std::sync::mpsc::channel;
use std::{thread, time};

slint::include_modules!();

fn add_with_check(value: u32) -> u32 {
    if value >= 3596400 {
        return value;
    }
    value + 1
}

fn time_pass_to_str(time_pass: &u32) -> String {
    let hour: u32 = *time_pass / 3600;
    let minute: u32 = (*time_pass - hour * 3600) / 60;
    let second: u32 = *time_pass - hour * 3600 - minute * 60;
    std::format!("{hour:02}:{minute:02}:{second:02}")
}

enum Command {
    Pulse,
    Pause,
    Continue,
    Reset,
    Setting(bool, u32),
}

fn main() -> Result<(), slint::PlatformError> {
    let (switch_sender, switch_receiver) = channel::<bool>();
    let (command_sender, command_receiver) = channel::<Command>();

    let ui = AppWindow::new()?;

    let switch_for_pause = switch_sender.clone();
    let command_for_pause = command_sender.clone();
    let ui_weak = ui.as_weak();
    ui.on_pause(move || {
        let ui = ui_weak.unwrap();
        if ui.get_is_pause() {
            command_for_pause.send(Command::Pause).unwrap();
            switch_for_pause.send(false).unwrap();
        } else {
            command_for_pause.send(Command::Continue).unwrap();
            switch_for_pause.send(true).unwrap();
        }
    });

    let switch_for_reset = switch_sender.clone();
    let command_for_reset = command_sender.clone();
    ui.on_reset(move || {
        command_for_reset.send(Command::Reset).unwrap();
        switch_for_reset.send(false).unwrap();
    });


    let mode_switch = command_sender.clone();
    ui.on_set_count_down(move |is_count_down, hour, minute, second| {
        let count_down_second = (hour * 3600 + minute * 60 + second) as u32;
        mode_switch
            .send(Command::Setting(is_count_down, count_down_second))
            .unwrap();
    });

    let ui_weak = ui.as_weak();
    ui.on_exit(move || {
        ui_weak.unwrap().hide().unwrap();
    });

    let ui_weak = ui.as_weak();
    ui.on_mouse_move(move |delta_x, delta_y| {
        let ui_weak = ui_weak.unwrap();
        let logical_pos = ui_weak
            .window()
            .position()
            .to_logical(ui_weak.window().scale_factor());
        ui_weak.window().set_position(slint::LogicalPosition::new(
            logical_pos.x + delta_x,
            logical_pos.y + delta_y,
        ));
    });

    let command_for_timmer = command_sender.clone();
    thread::spawn(move || loop {
        let mut is_run = switch_receiver.recv().unwrap();
        while is_run {
            match switch_receiver.try_recv() {
                Ok(value) => {
                    is_run = value;
                    if !is_run {
                        break;
                    }
                }
                Err(_) => {}
            }
            thread::sleep(time::Duration::new(1, 0));
            command_for_timmer.send(Command::Pulse).unwrap();
        }
    });

    let ui_weak = ui.as_weak();
    let end_count_sender = switch_sender.clone();
    thread::spawn(move || {
        let mut time_pass: u32 = 0;
        let mut is_run: bool = false;
        let mut change_updated: bool = true;
        let mut is_count_down: bool = false;
        let mut count_down_second: u32 = 0;
        loop {
            let command = command_receiver.recv().unwrap();
            match command {
                Command::Continue => is_run = true,
                Command::Pause => is_run = false,
                Command::Reset => {
                    is_run = false;
                    time_pass = 0;
                    change_updated = false;
                }
                Command::Pulse => {
                    if is_run {
                        time_pass = add_with_check(time_pass);
                        change_updated = false;
                    }
                }
                Command::Setting(icd, value) => {
                    is_count_down = icd;
                    count_down_second = value;
                    change_updated = false;
                }
            }

            if !change_updated {
                if is_count_down {
                    let remain_time = count_down_second - time_pass;
                    if remain_time == 0 {
                        is_run = false;
                        end_count_sender.send(false).unwrap();
                        ui_weak
                            .upgrade_in_event_loop(move |handle| handle.set_is_pause(true))
                            .unwrap();
                    }
                    ui_weak
                        .upgrade_in_event_loop(move |handle| {
                            handle.set_time_string(time_pass_to_str(&remain_time).into())
                        })
                        .unwrap();
                } else {
                    ui_weak
                        .upgrade_in_event_loop(move |handle| {
                            handle.set_time_string(time_pass_to_str(&time_pass).into())
                        })
                        .unwrap();
                }
                change_updated = true;
            }
        }
    });

    ui.run()
}
